package cn.com.weshare.lock.redislock;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author dujunguang
 * @description: 秒杀
 * @date: 2022/9/18 17:52
 * @version: 1.0.0
 **/
@RestController
public class SeckillController4 {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/buy4")
    public String buy4(@RequestParam(value = "user") Integer user) {
        // 锁的key值，设置成功就是拿到锁了
        String key = "buyUser";
        String value = UUID.randomUUID() + Thread.currentThread().getName();

        try {
            // 一起执行，保证原子性，具体保证是redis自身提供的命令，也就是文档中第一行的redis命令
            Boolean flagLock = stringRedisTemplate.opsForValue().setIfAbsent(key, value, 10L, TimeUnit.SECONDS);
            // 这个根据具体业务而定，其实这个时间不好确定，所以需要锁续期
            if (Boolean.FALSE.equals(flagLock)) {
                return "get redis lock fail";
            }

            String result = stringRedisTemplate.opsForValue().get("goods:001");
            int goodsNumber = result == null ? 0 : Integer.parseInt(result);

            if (goodsNumber > 0) {
                // 模拟异常
                if (user == 1) {
                    int i = 1 / 0;
                }
                int realNumber = goodsNumber - 1;
                stringRedisTemplate.opsForValue().set("goods:001", realNumber + "");
                System.out.println("buy success，surplus：" + realNumber + "件\t" + "port：" + serverPort);
                return "buy success：" + realNumber + "\tport：" + serverPort;
            } else {
                System.out.println("sell out：" + serverPort);
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } finally {
            // 删除的时候判断是不是自己的锁，简单演示就不加其他处理异常操作了
            if (stringRedisTemplate.opsForValue().get(key).equals(value)){
                stringRedisTemplate.delete(key);
            }
        }

        return "sell out port：" + serverPort;

    }


}
